<?php

namespace app\admins\controller;

use think\facade\Db;

class Article extends Base
{
    // 文章列表
    public function index()
    {
        if ($this->request->isAjax()) {
            $param = $this->request->param();
            // 搜索
            $map = [];
            if (!empty($param['search'])) {
                foreach ((array)$param['search'] as $k => $v) {
                    if (strlen($v)) $map[] = [$k, 'like', "%{$v}%"];
                }
            }
            // 查询
            $list = Db::table('article')->where('is_del', 0)->where($map)->order('id', 'desc');
            $data['count'] = $list->count();
            if ($data['count']) {
                $data['code'] = 0;
            } else {
                $data['code'] = 1;
                $data['msg'] = '暂无记录';
            }
            // 分页
            $list = $list->page($param['page'], $param['limit']);
            // 二维数组按键重组
            $cates = Db::table('cates')->where('status', 0)->column('*', 'id');
            $data['data'] = array_map(function ($item) use ($cates) {
                $item['preview'] = preg_match('/.+?\.(gif|jpg|jpeg|png|bmp|webp|psd|svg|tiff)$/i', $item['img']) ? '<img src="' . $item['img'] . '" alt="preview" style="width:70%;height:100%">' : '';
                $item['cat_name'] = isset($cates[$item['cat']]) ? $cates[$item['cat']]['name'] : '';
                // Nothing to use
                // $status_info = [0 => '<span style="color:green">正常</span>', 1 => '<span style="color:red">禁用</span>'];
                // $item['status_info'] = $status_info[$item['status']];
                return $item;
            }, $list->select()->toArray());
            exit(json_encode($data));
        }
        // 树形层级分类
        $data['cates'] = $this->tree_cates();
        return view('/article/index', $data);
    }

    // 添加
    public function add()
    {
        $data['cates'] = $this->tree_cates();
        return view('/article/add', $data);
    }

    // 保存
    public function save()
    {
        try {
            $this->validate($this->request->post(), [
                'title|标题' => 'require|token|unique:article',
                'content|内容' => 'require',
                'views|阅读量' => 'require|number',
                'hot|热门' => 'require|number',
                'date|日期' => 'require|date',
            ]);
        } catch (\Exception $e) {
            exit(json_encode(['code' => 1, 'msg' => $e->getMessage()]));
        }
        $data = $this->request->only(['title', 'content', 'img', 'cat', 'views', 'hot', 'status', 'date']);
        Db::table('article')->insert($data);
        // 附件状态
        $names = [];
        $data['img'] && Db::table('files')->where('path', $data['img'])->update(['status' => 0]);
        if (preg_match_all('/<img[^>]*src=["\']([^"\']*\/storage\/.+?\.[^"\']*)["\'][^>]*>/i', $data['content'], $matches)) {
            foreach ($matches[1] as $match) {
                $names[] = basename($match);
            }
        }
        $names && DB::table('files')->whereIn('file_name', array_unique($names))->update(['status' => 0]);
        exit(json_encode(['code' => 0, 'msg' => '保存成功']));
    }

    // 编辑
    public function edit()
    {
        $id = (int)input('get.id');
        $row = Db::table('article')->where('id', $id)->find();
        empty($row) && exit(json_encode(['code' => 1, 'msg' => '数据不存在']));
        $data['row'] = $row;
        $data['cates'] = $this->tree_cates();
        return view('/article/edit', $data);
    }

    // 保存编辑
    public function save_edit()
    {
        try {
            $this->validate($this->request->post(), [
                'id|ID' => 'require|number',
                'title|标题' => 'require|token|unique:article',
                'content|内容' => 'require',
                'views|阅读量' => 'require|number',
                'hot|热门' => 'require|number',
                'date|日期' => 'require|date',
            ]);
        } catch (\Exception $e) {
            exit(json_encode(['code' => 1, 'msg' => $e->getMessage()]));
        }
        $id = input('post.id');
        $row = Db::table('article')->where('id', $id)->find();
        empty($row) && exit(json_encode(['code' => 1, 'msg' => '数据不存在']));
        $data = $this->request->only(['title', 'content', 'img', 'cat', 'views', 'hot', 'status', 'date']);
        Db::table('article')->where('id', $row['id'])->update($data);
        // 附件状态
        $names = [];
        $data['img'] && Db::table('files')->where('path', $data['img'])->update(['status' => 0]);
        if (preg_match_all('/<img[^>]*src=["\']([^"\']*\/storage\/.+?\.[^"\']*)["\'][^>]*>/i', $data['content'], $matches)) {
            foreach ($matches[1] as $match) {
                $names[] = basename($match);
            }
        }
        $names && DB::table('files')->whereIn('file_name', array_unique($names))->update(['status' => 0]);
        exit(json_encode(['code' => 0, 'msg' => '保存成功']));
    }

    // 删除
    public function del()
    {
        $id = input('post.id');
        $rows = Db::table('article')->whereIn('id', $id)->select();
        $rows->isEmpty() && exit(json_encode(['code' => 1, 'msg' => '数据不存在']));
        Db::table('article')->whereIn('id', $rows->column('id'))->update(['is_del' => 1]);
        exit(json_encode(['code' => 0, 'msg' => '删除成功']));
    }

    // 属性修改
    public function modify()
    {
        try {
            $this->validate($this->request->post(), [
                'id|ID' => 'require|number',
                'field|字段' => 'require',
                'value|值' => 'require',
            ]);
        } catch (\Exception $e) {
            exit(json_encode(['code' => 1, 'msg' => $e->getMessage()]));
        }
        $id = input('post.id');
        $row = Db::table('article')->where('id', $id)->find();
        empty($row) && exit(json_encode(['code' => 1, 'msg' => '数据不存在']));
        // 非法字段
        $field = input('post.field');
        $value = input('post.value');
        (empty($field) || !is_string($field)) && exit(json_encode(['code' => 1, 'msg' => '字段错误']));
        is_null($value) && exit(json_encode(['code' => 1, 'msg' => '值错误']));
        !in_array($field, array_keys($row)) && exit(json_encode(['code' => 1, 'msg' => '该字段不允许修改']));
        $data = [];
        $data[$field] = $value;
        // 验证属性
        $rules = [
            'views|阅读量' => 'require|number',
            'hot|热门' => 'require|number',
        ];
        $validate = [];
        foreach ($rules as $key => $rule) {
            [$prop,] = explode('|', $key);
            if ($prop == $field) {
                $validate[$key] = $rule;
            }
        }
        if ($validate) {
            try {
                $this->validate($data, $validate);
            } catch (\Exception $e) {
                exit(json_encode(['code' => 1, 'msg' => $e->getMessage()]));
            }
        }
        Db::table('article')->where('id', $row['id'])->update($data);
        exit(json_encode(['code' => 0, 'msg' => '修改成功']));
    }

    /**
     * 回收站
     */
    public function recycle()
    {
        if ($this->request->isAjax()) {
            $param = $this->request->param();
            // 搜索
            $map = [];
            if (!empty($param['search'])) {
                foreach ((array)$param['search'] as $k => $v) {
                    if (strlen($v)) $map[] = [$k, 'like', "%{$v}%"];
                }
            }
            // 查询
            $list = Db::table('article')->where('is_del', 1)->where($map)->order('id', 'desc');
            $data['count'] = $list->count();
            if ($data['count']) {
                $data['code'] = 0;
            } else {
                $data['code'] = 1;
                $data['msg'] = '暂无记录';
            }
            // 分页
            $list = $list->page($param['page'], $param['limit']);
            // 二维数组按键重组
            $cates = Db::table('cates')->where('status', 0)->column('*', 'id');
            $data['data'] = array_map(function ($item) use ($cates) {
                $item['preview'] = preg_match('/.+?\.(gif|jpg|jpeg|png|bmp|webp|psd|svg|tiff)$/i', $item['img']) ? '<img src="' . $item['img'] . '" alt="preview" style="width:70%;height:100%">' : '';
                $item['cat_name'] = isset($cates[$item['cat']]) ? $cates[$item['cat']]['name'] : '';
                // Nothing to use
                // $status_info = [0 => '<span style="color:green">正常</span>', 1 => '<span style="color:red">禁用</span>'];
                // $item['status_info'] = $status_info[$item['status']];
                return $item;
            }, $list->select()->toArray());
            exit(json_encode($data));
        }
        // 树形层级分类
        $data['cates'] = $this->tree_cates();
        return view('/article/recycle', $data);
    }

    // 回收站删除
    public function recycle_del()
    {
        $id = input('post.id');
        $rows = Db::table('article')->whereIn('id', $id)->select();
        $rows->isEmpty() && exit(json_encode(['code' => 1, 'msg' => '数据不存在']));
        Db::table('article')->whereIn('id', $rows->column('id'))->delete();
        exit(json_encode(['code' => 0, 'msg' => '删除成功']));
    }

    // 回收站还原
    public function recycle_restore()
    {
        $id = input('post.id');
        $rows = Db::table('article')->whereIn('id', $id)->select();
        $rows->isEmpty() && exit(json_encode(['code' => 1, 'msg' => '数据不存在']));
        Db::table('article')->whereIn('id', $rows->column('id'))->update(['is_del' => 0]);
        exit(json_encode(['code' => 0, 'msg' => '还原成功']));
    }

    /**
     * 文章分类
     */
    public function cates()
    {
        // 树形层级分类
        if ($this->request->isAjax()) {
            $list = Db::table('cates')->order('sort', 'desc')->order('id', 'asc')->select();
            $list = $this->tree_cates();
            $data['count'] = count($list);
            if ($data['count']) {
                $data['code'] = 0;
            } else {
                $data['code'] = 1;
                $data['msg'] = '暂无记录';
            }
            $data['data'] = $list;
            exit(json_encode($data));
        }
        return view('/article/cates');
    }

    // 分类添加
    public function cate_add()
    {
        $data['pid'] = (int)input('get.pid');
        $data['cates'] = $this->tree_cates();
        return view('/article/cate_add', $data);
    }

    // 分类保存
    public function cate_save()
    {
        try {
            $this->validate($this->request->post(), [
                'name|分类名称' => 'require|token|unique:cates',
                'pid|上级分类' => 'require|number',
                'sort|排序' => 'require|integer',
            ]);
        } catch (\Exception $e) {
            exit(json_encode(['code' => 1, 'msg' => $e->getMessage()]));
        }
        $data = $this->request->only(['name', 'pid', 'sort', 'status']);
        Db::table('cates')->insert($data);
        exit(json_encode(['code' => 0, 'msg' => '保存成功']));
    }

    // 分类编辑
    public function cate_edit()
    {
        $id = (int)input('get.id');
        $row = Db::table('cates')->where('id', $id)->find();
        empty($row) && exit(json_encode(['code' => 1, 'msg' => '数据不存在']));
        $data['row'] = $row;
        $data['cates'] = $this->tree_cates();
        return view('/article/cate_edit', $data);
    }

    // 分类保存编辑
    public function cate_save_edit()
    {
        try {
            $this->validate($this->request->post(), [
                'id|ID' => 'require|number',
                'name|分类名称' => 'require|token|unique:cates',
                'pid|上级分类' => 'require|number',
                'sort|排序' => 'require|integer',
            ]);
        } catch (\Exception $e) {
            exit(json_encode(['code' => 1, 'msg' => $e->getMessage()]));
        }
        $id = input('post.id');
        $row = Db::table('cates')->where('id', $id)->find();
        empty($row) && exit(json_encode(['code' => 1, 'msg' => '数据不存在']));
        $data = $this->request->only(['name', 'pid', 'sort', 'status']);
        Db::table('cates')->where('id', $row['id'])->update($data);
        exit(json_encode(['code' => 0, 'msg' => '保存成功']));
    }

    // 分类删除
    public function cate_del()
    {
        $id = input('post.id');
        $rows = Db::table('cates')->whereIn('id', $id)->select();
        $rows->isEmpty() && exit(json_encode(['code' => 1, 'msg' => '数据不存在']));
        Db::table('cates')->whereIn('id', $rows->column('id'))->delete();
        exit(json_encode(['code' => 0, 'msg' => '删除成功']));
    }

    // 分类属性修改
    public function cate_modify()
    {
        try {
            $this->validate($this->request->post(), [
                'id|ID' => 'require|number',
                'field|字段' => 'require',
                'value|值' => 'require',
            ]);
        } catch (\Exception $e) {
            exit(json_encode(['code' => 1, 'msg' => $e->getMessage()]));
        }
        $id = input('post.id');
        $row = Db::table('cates')->where('id', $id)->find();
        empty($row) && exit(json_encode(['code' => 1, 'msg' => '数据不存在']));
        // 非法字段
        $field = input('post.field');
        $value = input('post.value');
        !in_array($field, array_keys($row)) && exit(json_encode(['code' => 1, 'msg' => '开玩笑呵']));
        $data = [];
        $data[$field] = $value;
        // 验证属性
        $rules = [
            'sort|排序' => 'require|integer',
        ];
        $validate = [];
        foreach ($rules as $key => $rule) {
            [$prop,] = explode('|', $key);
            if ($prop == $field) {
                $validate[$key] = $rule;
            }
        }
        if ($validate) {
            try {
                $this->validate($data, $validate);
            } catch (\Exception $e) {
                exit(json_encode(['code' => 1, 'msg' => $e->getMessage()]));
            }
        }
        Db::table('cates')->where('id', $row['id'])->update($data);
        exit(json_encode(['code' => 0, 'msg' => '修改成功']));
    }

    // 私有方法：树形层级分类
    private function tree_cates()
    {
        $cates = Db::table('cates')->order('sort', 'desc')->order('id', 'asc')->select();
        $cates = $this->trees($cates);
        $cates = array_map(function ($item) {
            $item['name'] = $item['level'] ? str_repeat('&nbsp;&nbsp;&nbsp;', $item['level']) . ' |-' . $item['name'] : $item['name'];
            return $item;
        }, $cates);
        return $cates;
    }
}
